-- RiskerEquipM
-- Created by huangr April/6/2016
-- 冒险系装备

module("RiskerEquipM", package.seeall);

local compassConfig = {};

local whenLeaveDungeon;
local whenNextFloor;

-- 载入配置表
local _init = false;
local loadCsv = function()
    if _init then return end
    _init = true;

    -- 转换下department信息表
    local compass_CSV = get_compass_bonus_CSV();
    for i = 1, #compass_CSV do
        if compassConfig[compass_CSV[i].career] == nil then
            compassConfig[compass_CSV[i].career] = {};
        end

        compassConfig[compass_CSV[i].career][compass_CSV[i].times] = compass_CSV[i];
    end

    compass_CSV = {};
end

-- 模块初始化
function init()
    loadCsv();

    EventMgr.removeAll("RiskerEquipM");

    -- 关注离开地牢事件
    EventMgr.register("RiskerEquipM", event.LEAVE_DUNGEON, whenLeaveDungeon);

    -- 关注玩家进入下一层的回调
    EventMgr.register("RiskerEquipM", event.NEXT_FLOOR, function()
        whenNextFloor();
    end);
end

-- 进入下一层回调
whenNextFloor = function()
    local compassInfo = ME.user.dbase:query("compass_info") or {};
    if type(compassInfo["bonus"]) == "table" then
        compassInfo["bonus"] = nil;
        ME.user.dbase:set("compass_info", compassInfo);
    end
end

-- 能否锻造宝物
function canForgeTreasure(treasureId)
    local cost = FormulaM.invoke("CALC_FORGE_TREASURE_COST", treasureId);

    -- 先判断消耗
    for k, v in pairs(cost) do
        local count = v[3];
        if ItemM.getAmount(ME.user, v[2]) < count then
            return false;
        end
    end

    -- 需要图纸
    local dbase = EquipM.query(treasureId, "dbase") or {};
    if dbase["need_drawing"] == 1 and not FormulaM.invoke("CAN_FORGE_SPECIAL_TREASURE") then
        -- 检查当前装备是否激活
        local activedDrawing = DungeonM.getDungeonMixedField("actived_drawing");

        if activedDrawing == nil then
            return false;
        end

        activedDrawing = string.explode(activedDrawing, "|");
        local value = tostring(treasureId);
        if table.indexOf(activedDrawing, value) == -1 then
            -- 未激活直接返回
            return false;
        end
    end

    return true;
end

-------------------------------
-- 锻造宝物
function forgeTreasure(treasureId)
    if not canForgeTreasure(treasureId) then
        return false;
    end
    local cost = FormulaM.invoke("CALC_FORGE_TREASURE_COST", treasureId);

    -- 先扣除材料
    for k, v in pairs(cost) do
        local count = v[3];
        if v[1] == 1 then
            ItemM.costAmount(ME.user, v[2], count);
        elseif v[1] == 2 then
            if not ME.user:costAttrib(cost[2], cost[3]) then
                -- 扣除失败
                return false;
            end
        end
    end

    -- 锻造成功
    local bonus = {1, treasureId, 1};
    BonusM.doBonus(bonus, "forge_treasure");

    -- 抛出锻造成功事件
    EventMgr.fire(event.FORGE_SUCCESS, {["treasure_id"] = treasureId, ["amount"] = 1});
    return true;
end

-- 获得升级魔法套装的消耗
function getUpgradeMagicSuitCost(equipId)
    local cost = FormulaM.invoke("CALC_UPGRADE_MAGIC_SUIT_COST", equipId);
    return cost;
end

-------------------------
-- 升级装备
function upgradeEquip(requireStyle, classId)
    if not DungeonM.checkDungeonAction() then
        -- 经检测，不允许执行地牢行为
        return false;
    end

    if true ~= canEquipUpgraded(classId, false, requireStyle) then
        -- 该装备不能升级
        return false;
    end

    -- 获取下一级装备编号
    local nextClassId = EquipM.query(classId, "next_class_id");

    if ItemM.getAmount(ME.user, classId) <= 0 then
        -- 装备数量不足
        return false;
    end

    local cost = getUpgradeMagicSuitCost(classId);
    if ItemM.getAmount(ME.user, cost[2]) < cost[3] then
        -- 消耗不足
        return false;
    end

    -- 扣除失败
    if not ItemM.costAmount(ME.user, cost[2], cost[3]) then
        return false;
    end

    -- 扣除装备
    if not ItemM.costAmount(ME.user, classId, 1) then
        -- 装备扣除失败了
        return false;
    end

    -- 替换成下一级装备
    ItemM.addAmount(ME.user, nextClassId, 1);

    -- 抛出装备升级事件
    EventMgr.fire(event.RISKER_UPGRADE_EQUIP, { ["classId"] = classId, ["nextClassId"] = nextClassId});

    return true;
end

-- 升级穿戴的装备
function upgradeWearEquip(requireStyle, classId)
    if true ~= canEquipUpgraded(classId, true, requireStyle) then
        -- 该装备不能升级
        return false;
    end

    local pos = 1;
    local equipType = EquipM.query(classId, "type");

    if not EquipM.getEquip(equipType, pos) then
        -- 该装备没有穿在身上
        return false;
    end

    local cost = getUpgradeMagicSuitCost(classId);
    if ItemM.getAmount(ME.user, cost[2]) < cost[3] then
        -- 消耗不足
        return false;
    end

    -- 扣除失败
    if not ItemM.costAmount(ME.user, cost[2], cost[3]) then
        return false;
    end

    -- 获取下一级装备编号
    local nextClassId = EquipM.query(classId, "next_class_id");

    -- 替换成下一级装备
    local equipments = ME.user.equipments;
    local equiped = equipments[equipType]
    equiped[pos] = nextClassId;

    -- 刷新附加属性
    PropM.refreshEffect(ME.user, "equip");

    EquipM.tryRecordSuitActive(nextClassId);

    -- 抛出装备升级事件
    EventMgr.fire(event.RISKER_UPGRADE_EQUIP, { ["classId"] = classId, ["nextClassId"] = nextClassId});

    return true;
end

-------------------------
-- 判断该装备能否升级
-- @param classId   装备编号
function canEquipUpgraded(classId, isEquiped, requireStyle)
    local equipInfo = EquipM.query(classId);

    if not equipInfo then
        -- 装备不存在
        return false;
    end

    -- EQUIP_STYLE_SPECIAL装备需求可以升级，dbase配置second_style
    local style = equipInfo["style"];
    local dbase = equipInfo["dbase"];
    if type(dbase["second_style"]) == "number" then
        style = dbase["second_style"];
    end

    -- 如果是装备系别不是要求系别不显示
    if requireStyle and style ~= requireStyle then
        return false;
    end

    -- 不是套装，不可以升级
    local suitId = equipInfo["suit"];
    if type(suitId) ~= 'number' or suitId <= 0 then
        -- 不是套装，无视
        return false;
    end

    -- 穿在身上的装备，只有物理偏向和魔法偏向才可以升阶
    if isEquiped == true then
        if style ~= EQUIP_STYLE_PHYSIC and
            style ~= EQUIP_STYLE_MAGIC then
            return false;
        end
    end

    -- 判断是否配置了下一级装备编号
    local nextClassId = equipInfo["next_class_id"];
    if type(nextClassId) ~= 'number' or
       nextClassId <= 0 then
       -- 未配置下一级装备编号
       return false;
    end

    if not EquipM.query(nextClassId) then
        -- 下一级装备不存在
        return false;
    end

    return true;
end

-- 查询罗盘相关信息
function queryCompass(careerId, times, path)
    local m = compassConfig[careerId][times];
    return m[path];
end

-- 检查罗盘的使用
function canUseCompass(classId)
    -- 检查当前玩家身上的罗盘
    if ItemM.getAmount(ME.user, classId) < 1 then
        return false;
    end

    -- 获得奖励相关的信息
    local compassInfo = ME.user.dbase:query("compass_info") or {};

    local times = tonumber(compassInfo["times"]);
    local layer = tonumber(compassInfo["layer"]);

    local pet = ME.user:getActivePet();
    if not pet then
        return false;
    end

    local careerId = FormulaM.invoke("GET_COMPASS_CAREER_ID", classId);

    local skillLevel = CareerM.getCareerLevel(pet, careerId);

    local maxTimes = skillLevel * 3;

    -- 次数已经达到
    if times >= maxTimes then
        return "compass_be_broken";
    end

    -- 当前层用不了
    local curLayer = DungeonM.currentLayer();
    if layer > 0 and curLayer - layer < 2 then
        return "cant_find_resource";
    end

    return true;
end

-- 获得罗盘奖励
function generateCompassBonus(classId)
    local careerId = FormulaM.invoke("GET_COMPASS_CAREER_ID", classId);

    -- 获得奖励相关的信息
    local compassInfo = ME.user.dbase:query("compass_info") or {};

    if type(compassInfo["bonus"]) == "table" and #table.keys(compassInfo["bonus"]) > 0 then
        return false;
    end

    local times = tonumber(compassInfo["times"]) + 1;
    local layer = tonumber(compassInfo["layer"]);

    local bonusRatio = queryCompass(careerId, times, "bonus_ratio");

    local weight = {};
    local sum = 0;
    local total = 0;
    for index, ratio in pairs(bonusRatio) do
        total = total + 1;

        weight[index] = ratio;
        -- 必须大于0，才去计算
        if ratio > 0 then
            sum = sum + ratio;
        end
    end

    -- 奖励信息
    local bonusInfo = queryCompass(careerId, times, "bonus");

    -- 选择当前节点
    local count = 2
    local selectList = {};
    while(count > 0) do
        count = count - 1;
        local seed = DungeonM.getRandSeed("COMPASS_BONUS");
        local selectNum = seed % sum;

        local weightSum = 0;
        for index = 1, total do
            if weight[index] > 0 then
                weightSum = weightSum + weight[index];
                if selectNum < weightSum then
                    selectList[index] = bonusInfo[index];
                    sum = sum - weight[index];

                    weight[index] = 0;
                    break;
                end
            end
        end
    end

    compassInfo["bonus"] = selectList;

    ME.user.dbase:set("compass_info", compassInfo);

    return true;
end

-- 能否领取罗盘奖励奖励
function canTakeCompassBonus(classId)
    local compassInfo = ME.user.dbase:query("compass_info") or {};

    local times = tonumber(compassInfo["times"]) + 1;

    local careerId = FormulaM.invoke("GET_COMPASS_CAREER_ID", classId);

    local cost = queryCompass(careerId, times, "cost");

    -- 未取到消耗信息
    if not cost then
        return false;
    end

    -- 消耗
    if ME.user:queryAttrib(cost[2]) < cost[3] then
        return "search_point_not_nough";
    end

    return true;
end

-- 使用罗盘获得奖励
function takeCompassBonus(classId, index)
    -- 消耗
    local compassInfo = ME.user.dbase:query("compass_info") or {};

    local times = tonumber(compassInfo["times"]) + 1;

    local careerId = FormulaM.invoke("GET_COMPASS_CAREER_ID", classId);

    local cost = queryCompass(careerId, times, "cost");

    if not cost then
        return false;
    end

    -- 消耗属性
    if not ME.user:costAttrib(cost[2], cost[3]) then
        return false;
    end

    -- 所有次数用完，罗盘将消失
    local pet = ME.user:getActivePet();
    if not pet then
        return false;
    end

    local skillLevel = CareerM.getCareerLevel(pet, careerId);
    local maxTimes = skillLevel * 3;
    if CareerM.isCareerMaxLevel(pet, careerId) and times >= maxTimes then
        if not ItemM.costAmount(ME.user, classId, 1) then
            return false;
        end
    end

    local curLayer = DungeonM.currentLayer();

    local bonus = compassInfo["bonus"][index];

    BonusM.clearBonusCollect();
    BonusM.startBonusCollect();

    BonusM.doBonus(bonus, "compass_bonus");

    -- 探险家
    local ok = false;
    if careerId == 202 then
        ok = SlimeEventM.triggerEvent(330, {["petId"] = pet.classId});
    else
        ok = SlimeEventM.triggerEvent(331, {["petId"] = pet.classId, ["times_limit"] = true});
    end

    if ok and careerId == 203 then
        local times = tonumber(BuffDataM.query("compass_gem_bonus", 1));
        BuffDataM.set("compass_gem_bonus", 1, times + 1);
    end


    local bonusList = table.deepcopy(BonusM.getBonusCollect());

    BonusM.endBonusCollect();
    BonusM.clearBonusCollect();

    EventMgr.fire(event.COMPASS_BONUS, {["bonus"] = bonusList});

    compassInfo["times"] = times;
    compassInfo["layer"] = curLayer;
    compassInfo["bonus"] = nil;

    ME.user.dbase:set("compass_info", compassInfo);

    return true;
end

-- 离开地牢时删除罗盘相关使用信息
whenLeaveDungeon = function ()
    -- body
    ME.user.dbase:delete("compass_info");
end

-- 当前罗盘使用的最大次数
function getCompassMaxTimes(classId)
    local careerId = FormulaM.invoke("GET_COMPASS_CAREER_ID", classId);

    local pet = ME.user:getActivePet();
    local careerLevel = tonumber(CareerM.getCareerLevel(pet, careerId));

    return careerLevel * 3;
end